﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base.Security;

namespace TestPermission.Module
{
    public class CustomObjectAccessComparer : ObjectAccessComparer
    {
        #region MemberLevel
        public override bool IsMemberReadGranted(Type requestedType, string propertyName, SecurityContextList securityContexts)
        {
            ITypeInfo typeInfo = XafTypesInfo.Instance.FindTypeInfo(requestedType);
            IMemberInfo memberInfo = typeInfo.FindMember(propertyName);
            foreach (IMemberInfo currentMemberInfo in memberInfo.GetPath())
            {
                if (!SecuritySystem.IsGranted(new MemberAccessPermission(currentMemberInfo.Owner.Type, currentMemberInfo.Name, MemberOperation.Read)))
                {
                    return false;
                }
            }
            return base.IsMemberReadGranted(requestedType, propertyName, securityContexts);
        }
        public override bool IsMemberModificationDenied(object targetObject, IMemberInfo memberInfo)
        {
            foreach (IMemberInfo currentMemberInfo in memberInfo.GetPath())
            {
                if (!SecuritySystem.IsGranted(new MemberAccessPermission(currentMemberInfo.Owner.Type, currentMemberInfo.Name, MemberOperation.Write)))
                {
                    return true;
                }
            }
            return base.IsMemberModificationDenied(targetObject, memberInfo);
        }

        #endregion

        #region ConditionObject
        public override bool IsSubsetOf(ObjectAccessPermission sourcePermission, ObjectAccessPermission targetPermission)
        {
            ObjectAccessPermission mergedTargetPermission = MergeTargetWithConditionalPermission(targetPermission, sourcePermission.Contexts);
            return base.IsSubsetOf(sourcePermission, mergedTargetPermission);
        }
        static ObjectAccessPermission MergeTargetWithConditionalPermission(ObjectAccessPermission targetPermission, SecurityContextList contexts)
        {
            if (contexts.TargetObjectContext != null && contexts.TargetObjectContext.TargetObject != null)
            {
                object targetObject = contexts.TargetObjectContext.TargetObject;
                ConditionalObjectAccessPermission validatedConditionalPermission = ConditionalPermission.FilterUnfitItems(targetObject);
                return (ObjectAccessPermission)validatedConditionalPermission.Union<ObjectAccessPermission>(targetPermission);
            }
            return targetPermission;
        }
        static ConditionalObjectAccessPermission ConditionalPermission
        {
            get
            {
                IUser user = (IUser)SecuritySystem.Instance.User;
                if (user != null)
                    return user.GetUserPermission<ConditionalObjectAccessPermission>() ?? new ConditionalObjectAccessPermission();
                return new ConditionalObjectAccessPermission();
            }
        }
        #endregion
    }
}
